home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Prog
/
T
/
TCL⁄C 1.1.2 Update.cpt
/
THINK C 5.0 Folder
/
THINK Class Library 1.1
/
Dialog classes
/
CDLOGDialog.c
next >
Wrap
Text File
|
1991-09-30
|
22KB
|
748 lines
/******************************************************************************
CDLOGDialog.c
Subclass of CDialog that can be create from DLOG/DITL
resources. The standard dialog items are represented
by their closest TCL analogs.
SUPERCLASS = CDialog
Copyright © 1991 Symantec Corporation. All rights reserved.
******************************************************************************/
#include "CDLOGDialog.h"
#include "CButton.h"
#include "CCheckBox.h"
#include "CRadioControl.h"
#include "CIntegerText.h"
#include "CPicture.h"
#include "CIconPane.h"
#include "CPaneBorder.h"
#include "CRadioGroupPane.h"
#include "CBartender.h"
#include "TBUtilities.h"
#include "CPanorama.h"
#include "CList.h"
#include <Packages.h>
typedef struct tItemList
{
short maxIndex;
tDITLItem items[];
} tItemList, *tItemListPtr, **tItemListHndl;
extern CBartender *gBartender;
static void CollectUntil( char delimiter, StringPtr text, short *index,
StringPtr returnStr);
/******************************************************************************
IDLOGDialog
Initialize a dialog window from DLOG/DITL resources.
******************************************************************************/
void CDLOGDialog::IDLOGDialog( short DLOGid, CDesktop *anEnclosure,
CDirector *aSupervisor)
{
DialogTHndl dlogTemplate = NULL;
Rect boundsRect;
SignedByte savedState;
Boolean makeScrollable;
staticTextFont = editTextFont = 0; /* use the system font */
staticTextSize = editTextSize = 0; /* use TE's default size */
defaultBorderPen = 1; /* default to border of 1 pixel */
/* Get the DLOG resource template */
dlogTemplate = (DialogTHndl) GetResource( 'DLOG', DLOGid);
FailNILRes( dlogTemplate);
/* Get window size from the template */
boundsRect = (**dlogTemplate).boundsRect;
/* If the procID is documentProc or zoomDocProc then give the window */
/* horizontal and vertical scroll bars and a size box. */
procID = (**dlogTemplate).procID;
makeScrollable = (procID == documentProc) || (procID == zoomDocProc);
CDialog::INewDialog( &boundsRect, kNotVisible, procID,
(**dlogTemplate).goAwayFlag, anEnclosure, aSupervisor);
MakePanorama( makeScrollable, makeScrollable, makeScrollable);
savedState = HGetState( (Handle) dlogTemplate);
HLock( (Handle) dlogTemplate);
/* Get the window title from the template */
SetTitle( (**dlogTemplate).title);
HSetState( (Handle) dlogTemplate, savedState);
/* Get the DITL resource and create all the dialog items */
AddDITLItems( (**dlogTemplate).itemsID, 0);
} /* CDialog::IDLOGDialog */
/******************************************************************************
AddDITLItems
Parse the DITL resource, and create the appropriate TCL panes.
A separate method is called for each item type, so it is not usually
necessary to override this method.
******************************************************************************/
void CDLOGDialog::AddDITLItems( short DITLid, long baseID)
{
tItemListHndl itemList = NULL;
SignedByte savedState;
short currIndex, maxIndex, dataSize;
Boolean fDisabled;
register tDITLItem *ditlItem;
short itemWidth, itemHeight;
LongPt itemTopLeft;
CView *enclosure;
CPane *newItem;
TRY
{
/* Get the DITL item list */
itemList = (tItemListHndl) GetResource( 'DITL', DITLid);
FailNILRes( itemList);
savedState = HGetState( (Handle) itemList);
MoveHHi( (Handle) itemList);
HLock( (Handle) itemList);
maxIndex = (**itemList).maxIndex; /* index of last item in list */
ditlItem = (**itemList).items; /* point to the first DITL item */
/* iterate over all the items in the DITL resource */
/* and create the TCL panes on the fly */
for (currIndex = 0; currIndex <= maxIndex; currIndex++)
{
/* Is this item disabled? */
fDisabled = ditlItem->itemType & itemDisable;
/* Get size of the item, and the pad it for word */
/* alignment if necessary */
dataSize = ditlItem->itemLength;
if (dataSize & 1) ++dataSize;
/* Find the "best fit" enclosure for the new item */
enclosure = FindEnclosingView( &ditlItem->itemRect);
/* Get the dimensions for the new item */
itemWidth = ditlItem->itemRect.right - ditlItem->itemRect.left;
itemHeight = ditlItem->itemRect.bottom - ditlItem->itemRect.top;
/* If the enclosure for the new item is not the dialog */
/* itself, then we should transform the top left to the */
/* enclosure's coordinates. Note that the item rect in */
/* ditlItem is passed unmodified to the item creation */
/* methods. */
((CPane*) enclosure)->WindToFrame( topLeft( ditlItem->itemRect),
&itemTopLeft);
/* Switch on the item type. We must strip off the */
/* enable bit to do so. */
switch( ditlItem->itemType & 0x7F)
{
/* User Items */
case userItem:
newItem = AddDITLUserItem( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
/* Push Buttons */
case ctrlItem + btnCtrl:
newItem = AddDITLPushBtn( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
/* Check boxes */
case ctrlItem + chkCtrl:
newItem = AddDITLCheckBox( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
/* Radio Buttons */
case ctrlItem + radCtrl:
newItem = AddDITLRadioBtn( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem,
currIndex + baseID + 1);
break;
/* 'CNTL' Resource Controls */
case ctrlItem + resCtrl:
newItem = AddDITLResControl( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
/* Static text */
case statText:
newItem = AddDITLStatText( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
/* Edit text */
case editText:
newItem = AddDITLEditText( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
/* Icons */
case iconItem:
newItem = AddDITLIcon( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
/* Pictures */
case picItem:
newItem = AddDITLPicture( itemWidth, itemHeight, itemTopLeft.h,
itemTopLeft.v, enclosure, ditlItem);
break;
default:
newItem = NULL;
break;
}
if (newItem)
{
/* Set the view ID of the new dialog item to its index in the DITL + */
/* the base ID supplied by the caller. */
newItem->SetID( currIndex + baseID + 1);
if (fDisabled)
/* +++ disable item? */;
else
{
newItem->SetWantsClicks( TRUE);
}
}
/* bypass C pointer arithmetic to point to next item */
ditlItem = (tDITLItem*) (((long) ditlItem) + dataSize + sizeof( tDITLItem));
}
HSetState( (Handle) itemList, savedState);
}
CATCH
{
if (itemList)
{
HSetState( (Handle) itemList, savedState);
}
}
ENDTRY;
} /* CDLOGDialog::AddDITLItems */
/******************************************************************************
FindEnclosingView
Find the view that completely encloses the given rectangle. DITLs have
no concept of nested items, but we can allow nested views to be specified
by checking whether the rectangle of an new item is completely
enclosed by the rectangle of any existing items.
The rectangle is taken to be in Window coordinates.
******************************************************************************/
typedef struct tEnclViewInfo
{
Rect boundsRect;
CView *enclosingView;
} tEnclViewInfo;
static Boolean View_FindEnclosing( CObject *aView, long infoAddr)
{
CView *view = (CView*) aView;
CView *subview = NULL;
tEnclViewInfo *viewInfo = (tEnclViewInfo*) infoAddr;
/* first check if the current view encloses the rect */
/* if it does, then check if any subview encloses it */
if (view->Contains( topLeft( viewInfo->boundsRect)) &&
view->Contains( botRight( viewInfo->boundsRect)))
{
if (view->itsSubviews)
{
subview = (CView*) view->itsSubviews->FirstSuccess1((TestFunc1) View_FindEnclosing,
infoAddr);
}
/* save the most specific view that encloses the rect, */
/* either a subview of this view, or this view */
if (!viewInfo->enclosingView) /* TCL 1.1.1 DLP 9/30/91 */
viewInfo->enclosingView = subview? subview : view;
return TRUE;
}
else return FALSE;
}
CView *CDLOGDialog::FindEnclosingView( Rect *boundsRect)
{
CView *foundView = NULL;
tEnclViewInfo viewInfo;
if (itsSubviews)
{
viewInfo.boundsRect = *boundsRect;
viewInfo.enclosingView = NULL;
foundView = (CView*) itsSubviews->FirstSuccess1( (TestFunc1) View_FindEnclosing,
(long) &viewInfo);
/* If foundView is not nil, then some subview encloses */
/* the rect. However, there may be a view nested within */
/* foundView that completely encloses the rect. */
/* viewInfo.enclosingView returns the best view */
foundView = viewInfo.enclosingView;
}
/* if no subview was found that completely encloses boundsRect */
/* then the enclosure defaults to the dialog itself */
return foundView? foundView : itsPanorama;
} /* CDLOGDialog::FindEnclosingView */
/******************************************************************************
AddDITLPushBtn
Add a button.
******************************************************************************/
CPane *CDLOGDialog::AddDITLPushBtn( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
CButton *btn;
Str255 titleStr;
long cmd;
/* make a copy of the button title */
CopyPString( &ditlItem->itemLength, titleStr);
/* ask the bartender to parse this string for us. */
gBartender->ParseItemString( titleStr, &cmd);
btn = new( CButton);
btn->INewButton( aWidth, aHeight, hEncl, vEncl, titleStr, TRUE,
pushButProc, enclosure, this);
btn->SetClickCmd( cmd);
return btn;
} /* CDLOGDialog::AddDITLPushBtn */
/******************************************************************************
AddDITLRadioBtn
Add a radio button.
******************************************************************************/
CPane *CDLOGDialog::AddDITLRadioBtn( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem,
long anID)
{
CRadioControl *radio = new( CRadioControl);
ASSERT( member( enclosure, CRadioGroupPane));
radio->INewRadioControl( aWidth, aHeight, hEncl, vEncl, &ditlItem->itemLength,
TRUE, enclosure, enclosure);
return radio;
} /* CDLOGDialog::AddDITLRadioBtn */
/******************************************************************************
AddDITLCheckBox
Add a checkbox
******************************************************************************/
CPane *CDLOGDialog::AddDITLCheckBox( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
CCheckBox *check = new( CCheckBox);
check->INewCheckBox( aWidth, aHeight, hEncl, vEncl, &ditlItem->itemLength,
TRUE, enclosure, this);
return check;
} /* CDLOGDialog::AddDITLCheckBox */
/******************************************************************************
AddDITLResControl
Resource controls are not supported by this class.
******************************************************************************/
CPane *CDLOGDialog::AddDITLResControl( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
return NULL;
} /* CDLOGDialog::AddDITLResControl */
/******************************************************************************
AddDITLStatText
Add a static text item. If the item text begins with the character '@',
it is considered an overloaded item and the rest of the text is passed
to the AddOverloadedItem method.
The text font and size are controlled by the staticTextFont and
staticTextSize instance variables.
******************************************************************************/
CPane *CDLOGDialog::AddDITLStatText( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
CEditText *text;
unsigned char length;
Str255 itemText;
/* first check for overloading of static text items */
/* overloading is signalled by a first character of '@' */
if ( (* (char*) ditlItem->itemData) == '@')
{
length = Min( ditlItem->itemLength - 1, 255);
BlockMove( ((char*) ditlItem->itemData) + 1, &itemText[1], length);
itemText[0] = length;
return AddOverloadedItem( itemText, aWidth, aHeight, hEncl, vEncl,
enclosure, ditlItem);
}
else
{
text = new( CEditText);
text->IEditText( enclosure, this, aWidth, aHeight,
hEncl, vEncl,
sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
text->Specify( kNotEditable, kNotSelectable, kNotStylable);
text->SetFontNumber( staticTextFont);
if (staticTextSize > 0)
text->SetFontSize( staticTextSize);
if (ditlItem->itemLength)
text->SetTextPtr( (Ptr) ditlItem->itemData, ditlItem->itemLength);
return text;
}
} /* CDLOGDialog::AddDITLStatText */
/******************************************************************************
AddDITLEditText
Add an edit text item. The text font and size are controlled by the
editTextFont and editTextSize instance variables.
*******************************************************************************/
CPane *CDLOGDialog::AddDITLEditText( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
CDialogText *text;
text = new( CDialogText);
text->IDialogText( enclosure, this, aWidth, aHeight,
hEncl, vEncl,
sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
text->SetFontNumber( editTextFont);
if (editTextSize > 0)
text->SetFontSize( editTextSize);
if (ditlItem->itemLength)
text->SetTextPtr( (Ptr) ditlItem->itemData, ditlItem->itemLength);
return text;
} /* CDLOGDialog::AddDITLEditText */
/******************************************************************************
AddDITLIcon
Add an icon
******************************************************************************/
CPane *CDLOGDialog::AddDITLIcon( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
CIconPane *icon;
icon = new( CIconPane);
icon->IIconPane( enclosure, this, hEncl, vEncl,
sizFIXEDSTICKY, sizFIXEDSTICKY, ditlItem->itemData[0],
TRUE);
return icon;
} /* CDLOGDialog::AddDITLIcon */
/******************************************************************************
AddDITLPicture
Add a picture
******************************************************************************/
CPane *CDLOGDialog::AddDITLPicture( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
CPicture *pict = new( CPicture);
pict->IPicture( enclosure, this, aWidth, aHeight,
hEncl, vEncl, sizFIXEDSTICKY, sizFIXEDSTICKY);
pict->UsePICT( ditlItem->itemData[0]); /* pass resource ID of PICT */
return pict;
} /* CDLOGDialog::AddDITLPicture */
/******************************************************************************
AddDITLUserItem
Add a user item. User items are converted to simple bordered panes
that use the defaultBorderPen thickness.
******************************************************************************/
CPane *CDLOGDialog::AddDITLUserItem( short aWidth, short aHeight, short hEncl,
short vEncl, CView *enclosure, tDITLItem *ditlItem)
{
CPane *pane = new( CPane);
CPaneBorder *border;
Rect margin;
pane->IPane( enclosure, this, aWidth, aHeight, hEncl, vEncl,
sizFIXEDSTICKY, sizFIXEDSTICKY);
border = new( CPaneBorder);
border->IPaneBorder( kBorderFrame);
border->SetPenSize( defaultBorderPen, defaultBorderPen);
pane->SetBorder( border);
return pane;
} /* CDLOGDialog::AddDITLUserItem */
/******************************************************************************
AddOverloadedItem
View types that have no direct dialog mgr analog may be added
by overloading the static text item. The types support are:
TYPE STATIC TEXT
---- -----------
Any Pane resource @$ClassName$ResType$ResID
e.g. @CPopupMenuPane$Popm$1000
would create a CPopupMenuPane from the template in
the resource 'Popm' 1000. The size and location
of the pane are taken from the dialog item rect,
not from the resource.
CRadioGroupPane @RadioGroupPane
CIntegerText @# must be first two characters
To supply min and max values enter
@#<min>#<max>,
e.g. @#100#200 (see Demo.π.rsrc DITL 1026)
CDialogText/ constraints @!! - creates required field, no max length
@!<num> - not required, max length is num
e.g. @!10 max length is 10
@!!<num> - required field with max length
e.g. @!!10
Other overloaded types may be created by overriding this method.
******************************************************************************/
CPane *CDLOGDialog::AddOverloadedItem( StringPtr itemText, short aWidth, short aHeight,
short hEncl, short vEncl,
CView *enclosure, tDITLItem *ditlItem)
{
Str255 numStr;
short index;
if (Length( itemText) == 0) return NULL;
if (itemText[1] == '$') // Create from resource
{
ResType type;
long resID;
Str255 className;
CPane *newPane;
PaneTemp savedTemplate, *theTemp;
Handle templateRes;
SignedByte savedState;
// collect the class name, resource type and ID
index = 2;
CollectUntil( '$', itemText, &index, className);
if (Length( className) == 0) return;
++index;
CollectUntil( '$', itemText, &index, numStr);
if (Length( numStr) == 0) return;
BlockMove( &numStr[1], &type, sizeof(ResType));
++index;
CollectUntil( ' ', itemText, &index, numStr);
if (Length( numStr) == 0) return;
StringToNum( numStr, &resID);
// get the resource, save the location and size, then
// restore it after the pane is created.
templateRes = GetResource( type, resID);
FailNILRes( templateRes);
savedState = HGetState( templateRes);
HNoPurge( templateRes);
theTemp = *(PaneTemp**) templateRes;
savedTemplate = **(PaneTemp**)templateRes;
theTemp->width = aWidth;
theTemp->height = aHeight;
theTemp->hEncl = hEncl;
theTemp->vEncl = vEncl;
// now make the pane
newPane = new_by_name( PtoCstr(className));
if (!newPane) Failure( paramErr, excNewByNameFailed);
ASSERT( member( newPane, CPane));
newPane->IViewRes( type, resID, enclosure, this);
HSetState( templateRes, savedState);
**(PaneTemp**) templateRes = savedTemplate; /* TCL 1.1.1 DLP 9/18/91 */
return newPane;
}
else if (itemText[1] == '#') // Create a CIntegerText
{
long min, max;
CIntegerText *text = new CIntegerText;
text->IIntegerText( enclosure, this, aWidth, aHeight,
hEncl, vEncl,
sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
text->SetFontNumber( editTextFont);
if (editTextSize > 0)
text->SetFontSize( editTextSize);
index = 2;
min = MINLONG;
max = MAXLONG;
CollectUntil( '#', itemText, &index, numStr);
if (Length( numStr)) StringToNum( numStr, &min);
// check if string not exhausted and have another '#'
if ((index < Length(itemText)) && (itemText[index] == '#'))
{
index++; // move past delimiter
CollectUntil( '#', itemText, &index, numStr);
if (Length( numStr)) StringToNum( numStr, &max);
}
text->SpecifyRange( min, max);
return text;
}
else if (itemText[1] == '!') // Create a CDialogText with constraints
{
Boolean required = FALSE;
short index = 2;
long maxChars = MAXLONG;
CDialogText *text = new CDialogText;
text->IDialogText( enclosure, this, aWidth, aHeight,
hEncl, vEncl,
sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
text->SetFontNumber( editTextFont);
if (editTextSize > 0)
text->SetFontSize( editTextSize);
// if next char is another '!', make this a required field
if (itemText[2] == '!')
{
index++;
required = TRUE;
}
// next text, if any, is max number of chars, no
// trailing delimiter is required, just collect until end of string
CollectUntil( '!', itemText, &index, numStr);
if (Length( numStr)) StringToNum( numStr, &maxChars);
text->SetConstraints( required, maxChars);
return text;
}
else if (EqualString( itemText, "\pRadioGroupPane", FALSE, FALSE))
{
CPaneBorder *border;
CRadioGroupPane *group = new CRadioGroupPane;
group->IRadioGroupPane( enclosure, this, aWidth, aHeight,
hEncl, vEncl, sizFIXEDSTICKY, sizFIXEDSTICKY);
border = new CPaneBorder;
border->IPaneBorder( kBorderFrame);
border->SetPenSize( defaultBorderPen, defaultBorderPen);
group->SetBorder( border);
return group;
}
return NULL;
} /* CDLOGDialog::AddOverloadedItem */
static void CollectUntil( char delimiter, StringPtr text, short *index,
StringPtr returnStr)
{
short i = *index, limit = Length( text);
Length( returnStr) = 0;
while ((text[i] != delimiter) && (i <= limit))
{
returnStr[ ++returnStr[0]] = text[i++];
}
if ( i > limit) i = limit;
*index = i;
}